
#include "./db.h"
#include "../types/string_t.h"
#include "../types/list_t.h"
#include "../util/lutils.h"

namespace lukv {

db::db() : key_spaces() { }

db::db(const db & _db) = default;

db::db(db && _db) noexcept : key_spaces(std::move(_db.key_spaces)) { }

db::~db() {
    for (auto & [k, v] : key_spaces) delete v;
}

std::pair<char, std::string> db::handle_f(const std::string & cmd) {
    std::vector<std::string> cmds = split_by_spaces(cmd);
    if (cmds.size() < 3) {
        LOG_ERR(ERR_SYNTAX);
        return { -1, ERR_SYNTAX };
    }
    const std::string & _op = cmds[1];
    if (_op == "get") {
        return handle_get(cmds);
    }
    else if (_op == "set") {
        return handle_set(cmds);
    }
    else if (_op == "del") {
        return handle_del(cmds);
    }
    else {
        LOG_ERR((ERR_OPT + _op));
        return { -1, ERR_OPT + _op };
    }
    return { };
}

std::pair<char, std::string> db::handle_get(const std::vector<std::string> & _cmds) {
    const std::string & _key = _cmds[2];
    if (key_spaces.find(_key) == key_spaces.end()) {
        LOG_ERR((ERR_NOK + _key));
        return { -1, ERR_NOK + _key };
    }
    return key_spaces[_key]->handle(_cmds);
}

std::pair<char, std::string> db::handle_set(const std::vector<std::string> & _cmds) {
    const std::string & _key = _cmds[2];
    if (key_spaces.find(_key) != key_spaces.end()) {
        return key_spaces[_key]->handle(_cmds);
    }
    else {
        key_spaces[_key] = create_obj(_cmds[0]);
        if (!key_spaces[_key]) {
            LOG_ERR(ERR_CRE_OBJ);
            return { -1, ERR_CRE_OBJ };
        }
        return key_spaces[_key]->handle(_cmds);
    }
    return { };
}

std::pair<char, std::string> db::handle_del(const std::vector<std::string> & _cmds) {
    const std::string & _key = _cmds[2];
    if (key_spaces.find(_key) == key_spaces.end()) {
        return { -1, ERR_NOK };
    }
    else {
        delete key_spaces[_key];
        key_spaces[_key] = nullptr;
        key_spaces.erase(_key);
        return { 0, OPT_SUCC };
    }
    return { };
}

base_type * db::create_obj(const std::string & _type) {
    if (_type == "string") {
        return new string_t();
    }
    else if (_type == "bitmap") {
    }
    else if (_type == "hash_map") {
    }
    else if (_type == "map") {
    }
    else if (_type == "list") {
        return new list_t();
    }
    else if (_type == "hash_set") {
    }
    else if (_type == "set") {
    }
    else {
        return nullptr;
    }
    return nullptr;
}

}

